/**
 * 
 */
package com.globallogic.training.university.property;

import java.util.*;

import com.globallogic.training.university.*;
import com.globallogic.training.university.study.Lessonable;

/**
 * An <code>Auditorium</code> object represents an auditorium of University
 * 
 * @author vasiliy.kulgaviy
 * 
 */
public class Auditorium {

	private String id;
	private Set<ScheduledTime> scheduledTimes = new LinkedHashSet<ScheduledTime>();
	private ScheduledTime possibleScheduledTime = START_SCHEDULED_TIME;

	private static final ScheduledTime START_SCHEDULED_TIME = new ScheduledTime(
			WeekDay.MONDAY, 0);

	/**
	 * Constructs Auditorium with a given identifier
	 * 
	 * @param id
	 *            identifier of the auditorium
	 */
	public Auditorium(String id) {
		this.id = id;
	}

	/**
	 * Returns the identifier of the auditorium
	 * 
	 * @return the identifier of the auditorium
	 */
	public String getId() {
		return id;
	}

	/**
	 * Schedules the auditory with the time selected by method
	 * <code>selectScheduledTime</code>
	 * 
	 * @return the time that is scheduled
	 */
	public ScheduledTime schedule() {

		scheduledTimes.add(possibleScheduledTime);

		return possibleScheduledTime;
	}

	/**
	 * Selects a possible scheduled time starting with the Week Day. The
	 * selected scheduled time is stored by <code>Auditorium</code> object
	 * 
	 * @param startWeekDay
	 *            the week day to start looking for a possible time to schedule
	 * @return the time possible to schedule, if no time found - null is
	 *         returned
	 */
	public ScheduledTime selectScheduledTime(WeekDay startWeekDay) {
		for (WeekDay weekDay : WeekDay.values()) {
			if (WeekDay.getIntValue(weekDay) < WeekDay
					.getIntValue(startWeekDay)) {
				continue;
			}

			for (int hour : ScheduledTime.getSchedulableHours()) {
				if (scheduledTimes.size() == 0) {
					if (generatePossibleTime(weekDay, hour) == null) {
						break;
					} else {
						return possibleScheduledTime;
					}
				}

				for (Iterator<ScheduledTime> itr = scheduledTimes.iterator(); itr.hasNext();) {
					ScheduledTime currentScheduledTime = (ScheduledTime) itr
							.next();
					if (currentScheduledTime.equals(new ScheduledTime(weekDay,
							hour))) {
						break;
					} else if (!itr.hasNext()) {
						if (generatePossibleTime(weekDay, hour) == null) {
							break;
						} else {
							return possibleScheduledTime;
						}
					}
				}
			}
		}

		return null;
	}

	/**
	 * Sets the possible scheduled time of the auditorium to the start of the
	 * week
	 */
	public void refreshPossibleScheduledTime() {
		possibleScheduledTime = START_SCHEDULED_TIME;
	}

	private ScheduledTime generatePossibleTime(WeekDay weekDay, int hour) {
		ScheduledTime newScheduledTime = new ScheduledTime(weekDay, hour);

		if (possibleScheduledTime.compareTo(newScheduledTime) >= 0) {
			return null;
		} else {
			possibleScheduledTime = newScheduledTime;
			return newScheduledTime;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object other) {
		if (this == other)
			return true;

		if (!(other instanceof Auditorium))
			return false;

		Auditorium otherAuditorium = (Auditorium) other;

		return id.equals(otherAuditorium.getId());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 17;
		int result = 37;

		result = prime * result + id.hashCode();

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("%s", id);
	}
}
